<html>
<head>
  <title>10.外观（Facade）模式</title>
  <basefont face="微软雅黑" size="2" />
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="exporter-version" content="YXBJ Windows/602628 (zh-CN, DDL); Windows/10.0.0 (Win64); EDAMVersion=V2;"/>
  <style>
    body, td {
      font-family: 微软雅黑;
      font-size: 10pt;
    }
  </style>
</head>
<body>
<a name="22193"/>
<h1>10.外观（Facade）模式</h1>
<div>
<table bgcolor="#D4DDE5" border="0">
<tr><td><b>创建时间：</b></td><td><i>2020/6/7 14:18</i></td></tr>
<tr><td><b>更新时间：</b></td><td><i>2021/1/11 7:49</i></td></tr>
<tr><td><b>作者：</b></td><td><i>Long Life Student</i></td></tr>
<tr><td><b>来源：</b></td><td><a href="https://github.com/PhycheLiu/DesignPattern_Study-Test"><i>https://github.com/PhycheLiu/DesignPattern_Study-Test</i></a></td></tr>
</table>
</div>
<br/>

<div>
<span><div><div><span style="font-size: 14pt; font-weight: bold;">一、基本描述</span></div><ul><li><div>为系统中的一组接口提供一个一致的界面，Facade 模式定义了一个高层接口，这个接口使得这一子系统更加容易使用。</div></li><li><div>将一个系统划分成若干个子系统有利于降低系统的复杂性，一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小。</div></li><li><div>外观模式之所以这么称呼，是因为它将一个或数个类的复杂的一切都隐藏在背后，只显露出一个干净美好的外观。</div></li><li><div>外观对象为子系统中较一般的设施提供了一个单一而简单的界面。</div></li><li><div>外观模式又叫门面模式。</div></li><li><div>外观模式的主要目的在于降低系统的复杂度。</div></li><li><div>引入外观模式之后，增加新的子系统或移除子系统都非常方便，客户类无需修改（或只需极少修改），只需要在外观类中增加或移除对子系统的引用即可。</div></li><li><div>外观模式是一个使用频率异常高的设计模式。</div></li><li><div>外观模式并不给系统增加任何新的功能，仅仅是简化调用接口。</div></li><li><div>几乎所有的软件中均可以看到外观模式的影子：1）B/S中的首页或导航页面；2）C/S中的菜单或工具栏。</div></li><li><div>所有涉及到与多个业务对象交互的场景都可以考虑使用到外观模式进行重构。</div></li><li><div><font style="font-size: 10pt;"><span style="box-sizing: border-box; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; font-size: 10pt; color: rgb(36, 41, 46); font-variant-caps: normal; font-variant-ligatures: normal;">Facade不应该参与子系统内的业务逻辑</span><span style="letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; font-size: 10pt; color: rgb(36, 41, 46); font-variant-caps: normal; font-variant-ligatures: normal;">。Facade只是一个接口，不应该有业务逻辑。</span></font></div></li><li><div><font color="#24292E">有了外观模式，通过实现一个提供更合理的接口的外观类，可以将一个复杂的子系统变得容易使用。如果需要复杂子系统的强大威力，还是可以使用原来的复杂的接口，但如果需要的是一个方便使用的接口，那就使用外观。</font></div></li><li><div><font color="#24292E">外观只是提供更直接的操作，并没有将原来的子系统阻隔起来，如果需要子系统类的更高层功能，还是可以使用原来的子系统。</font></div></li><li><div><font color="#24292E">外观模式提供简化接口的同时，依然将系统完整的功能暴露出来，以提供需要的人使用。</font></div></li><li><div>外观可以附加“聪明的”功能，让使用子系统更方便。</div></li><li><div>可以为一个子系统创建许多个外观。</div></li><li><div>外观不只是简化了接口，也将客户从组件的子系统中解耦。</div></li><li><div>外观的意图是要提供一个简单的接口，好让一个子系统更容易使用。</div></li></ul><div><span style="font-size: 14pt; font-weight: bold;">二、图例</span></div><div style="text-align: center;"><img src="10.外观（Facade）模式_files/Image.png" type="image/png" data-filename="Image.png" width="487"/></div><ul><li><div>Facade：知道哪些子系统类负责处理请求。将客户的请求代理给适当的子系统对象。Facade会将所有的从客户端发来的请求委派到相应的子系统去，即，Facade没有实际的业务逻辑，只是一个委托类。</div></li><li><div>子系统类：实现子系统的功能。处理由Facade对象指派的任务。没有Facade的任何相关信息，即没有指向Facade的指针。可以同时又一个或多个子系统，每个子系统都是一个类的集合，子系统不知道Facade的存在，对于子系统，Facade只是另外一个客户端。</div></li></ul><div><span style="font-size: 14pt; font-weight: bold;">三、优缺点</span></div><div><span style="font-weight: bold;">优点</span></div><ul><li><div>外观模式对客户屏蔽子系统组件，因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。</div></li><li><div>外观模式实现了子系统和客户之间的松耦合关系，而子系统内部的功能组件往往是紧耦合的。松耦合关系使得子系统的组件变化不会影响到它的客户。Facade 模式有助于建立层次结构系统，也有助于对对象之间的依赖关系分层。Facade 模式可以消除复杂的循环依赖关系。</div></li><li><div>如果应用需要，外观模式并不限制它们使用子系统类，因此你可以在系统易用性和通用性之间加以选择。</div></li></ul><div><span style="font-weight: bold;">缺点</span></div><ul><li><div>不符合“开闭原则”：对修改关闭，对扩展开放。</div></li></ul><div><span style="font-size: 14pt; font-weight: bold;">四、可能的改进</span></div><ul><li><div>可以引入一个抽象外观类。客户端针对抽象外观类进行编程，对于新的业务需求，无需修改原有外观类，只需对应增加一个新的外观类，在运行时具体确定使用哪个具体外观类。</div></li><li><div><font style="font-size: 10pt;"><span style="box-sizing: border-box; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><a href="https://github.com/PhycheLiu/DesignPattern_Study-Test/tree/master/Java/src/com/company/facade/section5" style="font-size: 10pt; font-variant-caps: normal; font-variant-ligatures: normal;">一个子系统可以有多个Facade</a></span><span style="letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; font-size: 10pt; color: rgb(36, 41, 46); font-variant-caps: normal; font-variant-ligatures: normal;">。当：1）Facade已经大到难以忍受的程度，或者2）子系统希望提供不同的访问路径，的时候，可以建立多个Facade以提供不同的高层模块来访问。</span></font></div></li></ul><div><span style="font-size: 14pt; font-weight: bold;">五、个人理解</span></div><ul><li><div>Facade 在分割分层系统这方面非常像一个网关。</div></li><li><div>有一些书上说客户端只能与Facade通信，这个说法是有问题的，原版的设计模式明确指出，一般用户可以与Facade通信，但是也可以直接同子系统中的某个类通信。</div></li><li><div>Facade特别简单，设置没有一个类图，只有一个示意图，但也正因为如此，各种实现均可以说自己是Facade，个人认为，Facade归根结底是一个接口，方便Client使用。</div></li><li><div>个人认为Facade不应参与业务逻辑，这并不是Facade模式本身的要求，一个参与业务逻辑的Facade也是Facade，但是参与业务逻辑之后，如果要修改Facade不太方便，另外此Facade就无法替换了，为后期的维护带来不便。</div></li><li><div>装饰者、适配器、外观</div><div>装饰者不改变接口，但加入责任</div><div>适配器将一个接口转成另一个接口</div><div>外观让接口更简单</div><div>外观和适配器可以包装许多类，但是外观的意图是简化接口，而适配器的意图是将接口转换成不同的接口。</div></li></ul><div><br clear="none"/></div><div><br clear="none"/></div><div><br/></div></div><div><br/></div></span>
</div></body></html> 